package com.zhuiYun.project.api.user.service.impl;

import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.zhuiYun.project.api.WxLogin.config.TencentCloudAuth;
import com.zhuiYun.project.api.user.entiy.User;
import com.zhuiYun.project.api.user.mapper.UserMapper;
import com.zhuiYun.project.api.user.model.UserModel;
import com.zhuiYun.project.api.user.service.UserService;
import com.zhuiYun.project.common.errorCode.CommonException;
import com.zhuiYun.project.common.errorCode.EmErrorCode;
import com.zhuiYun.project.common.response.CommonResult;
import com.zhuiYun.project.util.BeanUtils;
import com.zhuiYun.project.util.ObjectUtils;
import com.zhuiYun.project.util.RedisUtil;
import com.zhuiYun.project.util.UploadFileUtils;
import com.zhuiYun.project.util.constants.CommonConstants;
import com.zhuiYun.project.util.pageUtil.MybatisPageHelper;
import com.zhuiYun.project.util.pageUtil.PageRequest;
import com.zhuiYun.project.util.pageUtil.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Author Root
 * @Date 2023/4/4 9:53
 **/
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    JavaMailSender mailSender;

    @Autowired
    private UserMapper upUserMapper;
    /**
    * @Author Root
    * @Description修改用户信息
    * @Date 2023/4/4 14:01
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param userModel
    */
    @Override
    public Integer updateUser(MultipartFile imageFile, UserModel userModel) throws CommonException {
        //判断图片文件是否为空
        if(imageFile != null){
            //不为空返回string类型地址
            String s = UploadFileUtils.uploadFile(imageFile);
            //地址存储为id
            String avatarUrl= "http://101.43.223.224:8765/image/getImageById?id=" + s ;
            userModel.setAvatarUrl(avatarUrl);
        }
        User user = new User();
        //复制对象
        BeanUtils.copy(userModel,user);
        //通过主键修改用户信息
        int i = upUserMapper.updateByPrimaryKeySelective(user);
        return i;
    }

    /**
    * @Author Root
    * @Description通过id查询
    * @Date 2023/4/5 9:00
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param id
     *
    */
    @Override
    public CommonResult getUserById(Integer id) {
        User user = upUserMapper.selectByPrimaryKey(id);
        //id是否存在
        if(ObjectUtils.isNotEmpty(id)){
            //对象不为空
            if(ObjectUtils.isNotEmpty(user)){
                return CommonResult.ok(user);
            }else {
                return CommonResult.error(EmErrorCode.ID_NOT_OBJECT);
            }
        }else{
            return CommonResult.error(EmErrorCode.ID_NULL);
        }
    }
    /**
    * @Author Root
    * @Description  pc端用户校验旧密码
    * @Date 2023/4/18 14:57
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param id
* @param password
    */
    public CommonResult selectPassword(Integer id,String password){
        //用过id查询
        User user = upUserMapper.selectByPrimaryKey(id);
        //密码加密
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String passHash = encoder .encode(password);
        //旧密码解析后进行比较
        if(encoder.matches(password,user.getPassword())){
            return CommonResult.ok();
        }
       else{
           return CommonResult.error();
       }
    }
    /**
    * @Author Root
    * @Description 新增
    * @Date 2023/4/6 18:30
    * @Return java.lang.Integer
    * @param imageFile
    * @param userModel
    */
    @Override
    public Integer saveUser(MultipartFile imageFile, UserModel userModel) {
        //判断图片文件是否为空
        if(imageFile != null){
            String s = UploadFileUtils.uploadFile(imageFile);
            //地址存储为id
            String avatarUrl= "http://101.43.223.224:8765/image/getImageById?id=" + s ;
            userModel.setAvatarUrl(avatarUrl);
        }
        User user = new User();
        //model复制对象
        BeanUtils.copy(userModel,user);
        String password = user.getPassword();
        //加密密码
        String s = DigestUtils.md5DigestAsHex(password.getBytes());
        user.setPassword(s);
        user.setCreateTime(new Date());
        int i = upUserMapper.insertSelective(user);
        return i;
    }

    /**
    * @Author Root
    * @Description  通过id删除个人信息
    * @Date 2023/4/7 8:30
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param id
    */
    @Override
    public CommonResult deleteUser(Integer id) {
        //判断id是否为空
        if(id == null){
            return CommonResult.error(EmErrorCode.OBJECT_NOT_NULL);
        }else{
             upUserMapper.deleteByPrimaryKey(id);
            return CommonResult.ok();
        }
    }


    /**
    * @Author Root
    * @Description 分页查询
    * @Date 2023/4/12 8:42
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param userModel
    * @param pageRequest
    */
    @Override
    public CommonResult getUserByPage(UserModel userModel, PageRequest pageRequest) {
        //开启分页工具类
        MybatisPageHelper.startPage(pageRequest);
        //创建一个example对象
        Example example = new Example(User.class);
        //获取分页查询后的结果
        PageResult pageResult = MybatisPageHelper.getPageResult(upUserMapper.selectByExample(example));
        return CommonResult.ok(pageResult);
    }
    /**
    * @Author Root
    * @Description pc端用户修改个人密码
    * @Date 2023/4/18 14:58
    * @Return java.lang.Integer
    * @param userModel
    */
    @Override
    public Integer updatePassword(UserModel userModel) {
        User user = new User();
        //复制对象
        BeanUtils.copy(userModel,user);
        //密码加密
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String passHash = encoder .encode(user .getPassword());
        user.setPassword(passHash);
        //通过主键修改用户信息
        int i = upUserMapper.updateByPrimaryKeySelective(user);
        return i;
    }
    /**
    * @Author Root
    * @Description pc端用户修改个人邮箱
    * @Date 2023/4/18 14:58
    * @Return java.lang.Integer
    * @param userModel
    */
    public Integer updateMail(UserModel userModel){
        User user = new User();
        //复制对象
        BeanUtils.copy(userModel,user);
        user.setMail(user.getMail());
        //通过主键修改用户信息
        return upUserMapper.updateByPrimaryKeySelective(user);
    }
    /**
    * @Author Root
    * @Description pc端修改用户名
    * @Date 2023/4/18 16:19
    * @Return java.lang.Integer
    * @param userModel
    */
    public Integer updateUserName(UserModel userModel){
        User user = new User();
        //复制对象
        BeanUtils.copy(userModel,user);
        user.setUserName(user.getUserName());
        //通过主键修改用户信息
        return upUserMapper.updateByPrimaryKeySelective(user);
    }
    /**
    * @Author Root
    * @Description pc端修改用户手机号
    * @Date 2023/4/18 18:33
    * @Return java.lang.Integer
    * @param userModel
    */
    public Integer updatePhone(UserModel userModel){
        User user = new User();
        //复制对象
        BeanUtils.copy(userModel,user);
        user.setPhone(user.getPhone());
        //通过主键修改用户信息
        return upUserMapper.updateByPrimaryKeySelective(user);
    }

    /**
    * @Author Root
    * @Description pc端发送邮箱验证码
    * @Date 2023/4/18 14:59
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param mail
    */
    public CommonResult registerByMailCode(String mail) {
        int count = 1;//默认发送一次
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = null;
        try {
            helper = new MimeMessageHelper(mimeMessage, true);
            while (count-- != 0) {
                String codeNum = "";
                int[] code = new int[3];
                Random random = new Random();
                //自动生成验证码
                for (int i = 0; i < 6; i++) {
                    int num = random.nextInt(10) + 48;
                    int uppercase = random.nextInt(26) + 65;
                    int lowercase = random.nextInt(26) + 97;
                    code[0] = num;
                    code[1] = uppercase;
                    code[2] = lowercase;
                    codeNum += (char) code[random.nextInt(3)];
                }
                //标题4
                helper.setSubject("您的验证码为：" + codeNum);
                //内容
                helper.setText("您好！，感谢支持乐工坊。您正在申请修改邮箱，验证码为：" + "<h2>" + codeNum + "</h2>" + "千万不能告诉别人哦！", true);
                //邮件接收者
                helper.setTo(mail);
                //邮件发送者，必须和配置文件里的一样，不然授权码匹配不上
                helper.setFrom("389641604@qq.com");
                RedisUtil.set(mail + "login", codeNum, 300);
                // 邮箱登录将验证码存入redis的方式
                mailSender.send(mimeMessage);
            }
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return CommonResult.ok();
    }
    /**
    * @Author Root
    * @Description pc验证邮箱的验证码是否正确
    * @Date 2023/4/18 14:59
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param mail
    * @param code
    */
    public CommonResult determineMailCode(String mail,String code) {
        //获取redis中的验证码
        Object reidsCode = RedisUtil.get(mail + "login");
        //比较验证码
        if(code.equalsIgnoreCase((String) reidsCode)){
            return CommonResult.ok(200);
        }
        return CommonResult.ok(500);
    }
    /**
    * @Author Root
    * @Description pc邮箱是否重复
    * @Date 2023/4/18 15:02
    * @Return com.zhuiYun.project.api.upUser.entiy.User
    * @param mail
    */
    public User checkMail(String mail) {
        User user = new User();
        user.setMail(mail);
        //查询验证邮箱是否存在
        return upUserMapper.selectOne(user);
    }
    /**
    * @Author Root
    * @Description pc端手机号是否存在
    * @Date 2023/4/18 15:02
    * @Return com.zhuiYun.project.api.upUser.entiy.User
    * @param phone
    */
    public User checkPhone(String phone){
        User user = new User();
        user.setPhone(phone);
        //查询验证手机号是否存在
        return upUserMapper.selectOne(user);
    }
    /**
    * @Author Root
    * @Description pc用户名是否存在
    * @Date 2023/4/18 15:42
    * @Return com.zhuiYun.project.api.upUser.entiy.User
    * @param userName
    */
    public User checkUserName(String userName){
        User user = new User();
        user.setUserName(userName);
        //查询验证用户名是否存在
        return upUserMapper.selectOne(user);
    }

    /**
    * @Author Root
    * @Description pc端生成修改手机号发送验证码
    * @Date 2023/4/19 10:15
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param phone
    */
    public CommonResult sendPhoneCode(String phone) {
        // 生成验证码
        String newCode = "";
        //随机生成验证码
        Random random = new Random();
        for (int i = 0; i < 6; i++) {
            newCode += random.nextInt(10);
        }
        //是否成功发送验证
        boolean send = send(phone,newCode);
        if(send){
            RedisUtil.set(CommonConstants.CACHE_PHONE_CODE + newCode, newCode,600);
            return CommonResult.ok(newCode);
        }else {
            return CommonResult.error(EmErrorCode.CODE_IS_ERROR);
        }
    }

    /**
    * @Author Root
    * @Description pc端手机号验证码进行验证
    * @Date 2023/4/19 10:16
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param code
    */
    public CommonResult comparePhoneCode(String code) {
        //在redis'缓存中获取验证码
        String redisCode = (String) RedisUtil.get(CommonConstants.CACHE_PHONE_CODE + code);
        //判断是否为空
        if(ObjectUtils.isNotEmpty(redisCode)){
            //比较输入的验证码与redis中的验证码是否一致
            if(redisCode.equals(code)){
                return CommonResult.ok();
            }else {
                return CommonResult.error(EmErrorCode.CODE_IS_ERROR);
            }
        }else {
            return CommonResult.error(EmErrorCode.CODE_IS_ERROR);
        }
    }

    /**
    * @Description 获取建立会话的用户信息列表
    * @Author lzy
    * @Date 2023/4/21 10:42
    * @Return com.zhuiYun.project.common.response.CommonResult
    * @param userIds
    */
    @Override
    public CommonResult getUserListByUserIds(String userIds) {
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        String[] split = userIds.split(",");
        for (String s : split) {
            criteria.orEqualTo("id", s);
        }
        List<User> users = upUserMapper.selectByExample(example);
        return CommonResult.ok(users);
    }

    /**
    * @Author Root
    * @Description pc端手机号验证码的生成
    * @Date 2023/4/19 10:16
    * @Return boolean
    * @param phone
    * @param code
    */
    public boolean send(String phone, String code) {
        try {
            /* 必要步骤：
             * 实例化一个认证对象，入参需要传入腾讯云账户密钥对secretId，secretKey。
             * 这里采用的是从环境变量读取的方式，需要在环境变量中先设置这两个值。
             * 你也可以直接在代码中写死密钥对，但是小心不要将代码复制、上传或者分享给他人，
             * 以免泄露密钥对危及你的财产安全。
             * SecretId、SecretKey 查询: https://console.cloud.tencent.com/cam/capi */
            Credential cred = new Credential(TencentCloudAuth.SecretId, TencentCloudAuth.SecretKey);

            /** 实例化一个http选项，可选，没有特殊需求可以跳过 */
            HttpProfile httpProfile = new HttpProfile();
            /* 设置代理（无需要直接忽略）
             * httpProfile.setProxyHost("真实代理ip");
             * httpProfile.setProxyPort(真实代理端口); */

            /* SDK默认使用POST方法。
             * 如果你一定要使用GET方法，可以在这里设置。GET方法无法处理一些较大的请求 */
            httpProfile.setReqMethod("POST");
            /* SDK有默认的超时时间，非必要请不要进行调整
             * 如有需要请在代码中查阅以获取最新的默认值 */
            httpProfile.setConnTimeout(60);
            /* 指定接入地域域名，默认就近地域接入域名为 sms.tencentcloudapi.com ，也支持指定地域域名访问，例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com */
            httpProfile.setEndpoint("sms.tencentcloudapi.com");

            /* 非必要步骤:
             * 实例化一个客户端配置对象，可以指定超时时间等配置 */
            ClientProfile clientProfile = new ClientProfile();
            /* SDK默认用TC3-HMAC-SHA256进行签名
             * 非必要请不要修改这个字段 */
            clientProfile.setSignMethod("HmacSHA256");
            clientProfile.setHttpProfile(httpProfile);
            /* 实例化要请求产品(以sms为例)的client对象
             * 第二个参数是地域信息，可以直接填写字符串ap-guangzhou，支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */
            SmsClient client = new SmsClient(cred, "ap-guangzhou",clientProfile);
            /* 实例化一个请求对象，根据调用的接口和实际情况，可以进一步设置请求参数
             * 你可以直接查询SDK源码确定接口有哪些属性可以设置
             * 属性可能是基本类型，也可能引用了另一个数据结构
             * 推荐使用IDE进行开发，可以方便的跳转查阅各个接口和数据结构的文档说明 */
            SendSmsRequest req = new SendSmsRequest();

            /* 填充请求参数,这里request对象的成员变量即对应接口的入参
             * 你可以通过官网接口文档或跳转到request对象的定义处查看请求参数的定义
             * 基本类型的设置:
             * 帮助链接：
             * 短信控制台: https://console.cloud.tencent.com/smsv2
             * 腾讯云短信小助手: https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81 */

            /* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId，示例如1400006666
             * 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看 */
            req.setSmsSdkAppId(TencentCloudAuth.sdkAppId);

            /* 短信签名内容: 使用 UTF-8 编码，必须填写已审核通过的签名
             * 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信]
             * (https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看 */
            String signName = TencentCloudAuth.signName;
            req.setSignName(signName);

            /* 模板 ID: 必须填写已审核通过的模板 ID 1761869
             * 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信]
             * (https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看 */
            String templateId = TencentCloudAuth.templateId;
            req.setTemplateId(templateId);

            /** 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致，若无模板参数，则设置为空 */
            String[] templateParamSet = {code};
            req.setTemplateParamSet(templateParamSet);

            /* 下发手机号码，采用 E.164 标准，+[国家或地区码][手机号]
             * 示例如：+8613711112222， 其中前面有一个+号 ，86为国家码，13711112222为手机号，最多不要超过200个手机号 */
            String[] phoneNumberSet = {"+86"+phone};
            req.setPhoneNumberSet(phoneNumberSet);



            /* 通过 client 对象调用 SendSms 方法发起请求。注意请求方法名与请求对象是对应的
             * 返回的 res 是一个 SendSmsResponse 类的实例，与请求对象对应 */
            SendSmsResponse res = client.SendSms(req);

            /** 输出json格式的字符串回包 */
            System.out.println(SendSmsResponse.toJsonString(res));
            return true;

            /* 也可以取出单个值，你可以通过官网接口文档或跳转到response对象的定义处查看返回字段的定义
             * System.out.println(res.getRequestId()); */


        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
        }
        return false;
    }
}
